package pl.edu.mimuw.irs.core.model.analysis.dd;

import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

import pl.edu.mimuw.irs.core.model.analysis.RequirementPlace;
import pl.edu.mimuw.irs.core.model.design.processing.Requirement;

/* 
 * Class describing a dependency between activities that are in ancestor-descendant
 * relationship. Dependencies are storing information about ancestors, and their
 * requirements. Because of that we can create a graph of dependencies and search
 * it for occurrences of cycles. Later these cycles are analysed for deadlock
 * detection. This class is supposed to be a 1 to 1 related to in-graph 
 * different requirements (treating similar requirements instances as one - 
 * similar in meaning of their contained roles - not instances).
 */
public class Dependency implements IMarkable {

	// *** Attributes

	/* Requirement of this node */
	private Requirement requirement;
	/* 
	 * Place in analysis workflow that contains available tokens for the above 
	 * requirement (above requirement is also accessible through this place).
	 */
	private RequirementPlace requirementPlace;
	/*
	 * Set of activities that have used this dependency and yet have not finished
	 * working. This is used when some activity tries to take some other 
	 * requirement, but one of its descendants requires this dependency. In that case
	 * these stored activities will be asked if they can finish without resources
	 * taken by that "some" activity.
	 */
	private Set<ActivityWrapper> workingActivities;
	/* 
	 * Links to other dependencies for the above requirement. 
	 * Every dependency corresponds to some IRS node, that causes it. Because
	 * of this, every dependency is accessible through its mapped node.
	 */
	private Map<ActivityWrapper, Set<Dependency>> dependencies;
	/* 
	 * Cycles in which this dependency is present (through some IRSActivity).
	 */
//	private Map<ActivityWrapper, Set<Cycle>> cycles;
	/* Mark is used for cycles detection. */
	private boolean marked;
	// Getters and setters
	public Requirement getRequirement() {
		return requirement;
	}
	public RequirementPlace getRequirementPlace() {
		return requirementPlace;
	}
	public Set<ActivityWrapper> getWorkingActivities() {
		if (workingActivities == null) workingActivities = new LinkedHashSet<ActivityWrapper>();
		return workingActivities;
	}
	public Map<ActivityWrapper, Set<Dependency>> getDependencies() {
		if (dependencies == null) dependencies = new LinkedHashMap<ActivityWrapper, Set<Dependency>>();
		return dependencies;
	}
//	public Map<ActivityWrapper, Set<Cycle>> getCycles() {
//		if (cycles == null) cycles = new LinkedHashMap<ActivityWrapper, Set<Cycle>>();
//		return cycles;
//	}
	public boolean isMarked() {
		return marked;
	}
	@Override
	public void setMarked(boolean marked) {
		this.marked = marked;
	}
	
	// *** Constructors
	
	@Deprecated
	public Dependency(Requirement requirement) {
		this.requirement = requirement;
	}

	public Dependency(RequirementPlace requirementPlace) {
		this.requirement = requirementPlace.getRequirement();
		this.requirementPlace = requirementPlace;
	}
	
	// *** Methods
	
	@Override
	public String toString() {
		return "Dep(" + getRequirement() + ")";
	}
	
}
